#include<iostream>
#include<functional>
#include<memory>
#include"Tcpserver.hpp"
#include"Protocol.hpp"
#include"CalCulate.hpp"

using namespace protocol_ns;

void Usage(std::string proc)
{
    std::cout<<"Usage\n\t"<<proc<<std::endl;
}
using callback_t = std::function<Response(const Request&rep)>;
class Server
{
    public:
    Server(callback_t cd)
    :_cd(cd)
    {}
    void ServiceHelper(socket_sptr sockptr,InetAddr client)
    {
        int sockfd = sockptr->SockFd();
        LOG(DEBUG,"get a new link info %s:%d,fd:%d\n",client.Ip().c_str(),client.Port(),sockfd);
        std::string clientaddr ="[" +client.Ip()+"]" + ":" +std::to_string(client.Port())+"]";
        std::string inbuffer;
        while (true)
        {
            sleep(5);
            Request req;
            int  n = sockptr->Recv(&inbuffer);
            if(n<0)
            {
                LOG(DEBUG,"client quit",clientaddr.c_str());
                break;
            }

            //确认完整报文
            std::string package;
            while (true)
            {
              sleep(1);
              std::cout<<"inbuffer"<<inbuffer<<std::endl;
              package = Decode(inbuffer);
              if(package.empty())
              {
                break;
              }
              std::cout<<"------------------begin---------"<<std::endl;
              std::cout<<"resq string\n"
                        <<package<<std::endl;
                        //反序列化
                        req.Deserialize(package);
                        //业务处理
                        Response resp = _cd(req);

                        //应答做序列化
                        std::string send_str;
                        resp.Serialize(&send_str);

                        std::cout<<"resp serialize:"<<std::endl;
                        std::cout<<send_str<<std::endl;
                        //添加长度报头
                        send_str = Encode(send_str);
                        std::cout<<"resp encode:"<<std::endl;
                        std::cout<<send_str<<std::endl;

                        sockptr->Send(send_str);
            }
            
        }
        
    }
    private:
    callback_t _cd;
};

int main(int argc,char *argv[])
{
    if(argc!=2)
    {
        Usage(argv[0]);
        return 1;
    }
    uint16_t port = std::stoi(argv[1]);
    daemon(0,0);
    EnableFile();
    Calculate cal;
    Server calservice(std::bind(&Calculate::Excute,&cal,std::placeholders::_1));
    io_service_t service = std::bind(&Server::ServiceHelper,&calservice,std::placeholders::_1,std::placeholders::_2);
    std::unique_ptr<TcpServer> tsvr = std::make_unique<TcpServer>(port,service);
    tsvr->loop();
    return 0;
}